package com.hyfd.task;

import java.net.SocketTimeoutException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.conn.ConnectTimeoutException;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;

import com.hyfd.common.https.HttpsUtils;
import com.hyfd.common.utils.ToolSHA2_Codec;
import com.hyfd.dao.mp.OrderDao;
import com.hyfd.dao.mp.ProviderPhysicalChannelDao;
import com.hyfd.deal.Flow.SdllptFlowDeal;
import com.hyfd.rabbitMq.RabbitMqProducer;
import com.hyfd.rabbitMq.SerializeUtil;

public class SdllptTask {

	@Autowired
	ProviderPhysicalChannelDao providerPhysicalChannelDao;//物理通道信息
	@Autowired
	OrderDao orderDao;
	@Autowired
	RabbitMqProducer mqProducer;//消息队列生产者
	
	Logger log = Logger.getLogger(getClass());
//	@Scheduled(fixedDelay = 60000)
	public void querySdllptOrder(){//省网
		Map<String,Object> map = new HashMap<String,Object>();
		int flag = 2;//充值中
		try{
			String providerPhysicalChannelId = "0000000080"; //TODO 建立通道后确认此id
			Map<String,Object> channel = providerPhysicalChannelDao.selectByPrimaryKey(providerPhysicalChannelId);
			String appKey = String.valueOf(channel.get("appKey")); // appKey
			String appSecret = String.valueOf(channel.get("appSecret")); // appSecret
			String authInterfaceUrl = String.valueOf(channel.get("authInterfaceUrl")); // 认证地址
			String chargeResultInterfaceUrl=String.valueOf(channel.get("chargeResultInterfaceUrl"));	// 根据平台流水号查询订单地址
			
			String token = "";
			
			// 1.进行认证
			String authRequestReturnXml = authInterfaceRequest(appKey, appSecret, authInterfaceUrl);
			if (null == authRequestReturnXml) {
				String errorMessage = "山东统付流量定时任务[认证]请求:超时";
				log.error(errorMessage);
			}else{
				// 2.解析xml文件,获取Token信息
				token = getToken(authRequestReturnXml);
				
				Map<String, Object> param = new HashMap<String, Object>();
				param.put("dispatcherProviderId", providerPhysicalChannelId);
				param.put("status", "1");
				
				List<Map<String,Object>> orderList = orderDao.selectByTask(param);
				for(int i = 0 , size = orderList.size() ; i < size ; i++){
					Map<String,Object> order = orderList.get(i);
					String orderId = order.get("orderId")+"";
					map.put("orderId", orderId);
					
					// 3.订单查询接口
					String chargeQueryRequestReturnXml = chargeQueryRequest(appSecret, token, null, chargeResultInterfaceUrl, null, orderId);
					log.error("山东统付流量定时任务[订单查询],curids["+orderId+"]返回信息["+chargeQueryRequestReturnXml+"]");
					if (null == chargeQueryRequestReturnXml) {
						continue;
					}
					// 4.获取充值查询结果,如果返回值是null则代表没有查询到订单
					Map<String, String> chargeQueryMap = getChargeQueryResult(chargeQueryRequestReturnXml);
					if (null == chargeQueryMap) {
						continue;
					}
					String state = chargeQueryMap.get("status");
					String resultCode = chargeQueryMap.get("description");
					map.put("resultCode", state+":"+resultCode);
					if (state.equals("3")) {
						flag = 1;
					} else if (state.equals("4")){
						flag = 0;
					}
					
					map.put("status", flag);
					mqProducer.sendDataToQueue(RabbitMqProducer.Result_QueueKey, SerializeUtil.getStrFromObj(map));
				}
			}
		} catch (Exception e){
			log.error("山东流量平台查询出错"+e);
		}
	}
	
	/**
	 * <h5>功能:</h5>订单查询接口,先根据平台流水号查询,如果平台流水号不存在再根据上游流水号查询
	 * 
	 * @param appSecret
	 * @param token
	 * @param url01
	 *            根据上游流水号查询订单地址
	 * @param url02
	 *            根据平台流水号查询订单地址
	 * @param systemNun
	 *            上游流水号
	 * @param serialNum
	 *            平台流水号
	 * @return String
	 * 
	 * @author zhangpj @date 2016年8月25日
	 */
	public String chargeQueryRequest(String appSecret, String token,
			String url01, String url02, String systemNun, String serialNum) {
		// 2.1获取HTTP-X-4GGOGO-Signature的头信息,签名内容为SHA256Hex(appSecret)
		String returnInfo = "";
		String url = "";
		if (null == serialNum || "".equals(serialNum)) {
			url = url01 + systemNun + ".html";
		} else {
			url += url02 + serialNum + ".html";
		}
		String signatrue = getSHA256HexSignature(appSecret);
		try {
			returnInfo = HttpsUtils.doGet(url, null, token, signatrue,
					"application/xml", "utf-8");
			log.error("山东统付流量请求:" + url + "\n" + "token:" + token
					+ "\nsignatrue:" + signatrue);
		} catch (ConnectTimeoutException e) {
			log.error("山东统付流量请求,连接超时:" + url + "\n" + "token:" + token
					+ "\nsignatrue:" + signatrue);
		} catch (SocketTimeoutException e) {
			log.error("山东统付流量请求,Socket连接超时:" + url + "\n" + "token:" + token
					+ "\nsignatrue:" + signatrue);
		} catch (Exception e) {
			log.error("山东统付流量请求,其他异常:" + url + "\n" + "token:" + token
					+ "\nsignatrue:" + signatrue);
		}
		return returnInfo;
	}
	
	/**
	 * <h5>功能:</h5>进行认证,获取认证请求返回信息 post
	 * 
	 * @author zhangpj @date 2016年8月24日
	 * @param appKey
	 * @param appSecret
	 * @param url
	 *            认证地址
	 * @return
	 */
	public String authInterfaceRequest(String appKey, String appSecret,
			String url) {
		// 1.1获取认证接口的请求信息主体
		String bodyXml = getAuthBodyXml(appKey, appSecret);
		// System.out.println("1.1发起认证请求信息\r["+bodyXml+"]");
		String returnInfo = null;
		// 1.2发起请求认证
		try {
			returnInfo = HttpsUtils.post(url, bodyXml, "application/xml",
					"utf-8", 10000, 10000);
			log.error("山东统付流量请求:" + url + "\n" + "bodyXml:" + bodyXml);
		} catch (ConnectTimeoutException e) {
			log.error("山东统付流量请求,连接超时:" + url + "\n:bodyXml:" + bodyXml);
		} catch (SocketTimeoutException e) {
			log.error("山东统付流量请求,Socket连接超时:" + url + "\n:bodyXml:" + bodyXml);
		} catch (Exception e) {
			log.error("山东统付流量请求,其他异常:" + url + "\n:bodyXml:" + bodyXml);
		}
		// System.out.println("1.4发起认证请求返回信息\r["+bodyXml+"]");
		return returnInfo;
	}
	
	/**
	 * <h5>功能:</h5>获取认证接口的请求信息主体
	 * 
	 * @author zhangpj @date 2016年8月23日
	 * @param appKey
	 * @param appSecret
	 * @return String
	 */
	public String getAuthBodyXml(String appKey, String appSecret) {
		String requestTime = getUTCTime();

		// 签名内容为 SHA256Hex(appKey+requestTime+appSecret)
		String sign = getSHA256HexSignature(appKey + requestTime + appSecret);

		StringBuffer bodyXml = new StringBuffer();
		bodyXml.append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
		bodyXml.append("<Request>");
		bodyXml.append("<Datetime>").append(requestTime).append("</Datetime>");
		bodyXml.append("<Authorization>");
		bodyXml.append("<AppKey>").append(appKey).append("</AppKey>");
		bodyXml.append("<Sign>").append(sign).append("</Sign>");
		bodyXml.append("</Authorization>");
		bodyXml.append("</Request>");

		return bodyXml.toString();
	}
	
	/**
	 * <h5>功能:</h5>产品查询接口 get
	 * 
	 * @author zhangpj @date 2016年8月24日
	 * @param appSecret
	 * @param token
	 *            进行认证后获取的认证信息
	 * @param url
	 *            查询地址
	 * @return
	 */
	public String productsInterfaceRequest(String appSecret,
			String token, String url) {
		// 2.1获取HTTP-X-4GGOGO-Signature的头信息,签名内容为SHA256Hex(appSecret)
		String signatrue = getSHA256HexSignature(appSecret);
		String returnInfo = null;
		try {
			returnInfo = HttpsUtils.doGet(url, null, token, signatrue,
					"application/xml", "utf-8");
			log.error("山东统付流量请求:" + url + "\n" + "token:" + token
					+ "\nsignatrue:" + signatrue);
		} catch (ConnectTimeoutException e) {
			log.error("山东统付流量请求,连接超时:" + url + "\n" + "token:" + token
					+ "\nsignatrue:" + signatrue);
		} catch (SocketTimeoutException e) {
			log.error("山东统付流量请求,Socket连接超时:" + url + "\n" + "token:" + token
					+ "\nsignatrue:" + signatrue);
		} catch (Exception e) {
			log.error("山东统付流量请求,其他异常:" + url + "\n" + "token:" + token
					+ "\nsignatrue:" + signatrue);
		}
		return returnInfo;
	}
	
	/**
	 * <h5>功能:</h5>进行SHA256Hex加密
	 * 
	 * @author zhangpj @date 2016年8月23日
	 * @param str
	 * @return
	 */
	private String getSHA256HexSignature(String str) {
		String signature = "";
		try {
			signature = ToolSHA2_Codec.encodeSHA256Hex(str);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return signature;
	}
	
	/**
	 * <h5>功能:</h5>获取UTC时间 格式如:2016-08-23T10:02:16.748+08:00
	 * 
	 * @author zhangpj @date 2016年8月23日
	 * @return
	 */
	public String getUTCTime() {
		SimpleDateFormat sdf = new SimpleDateFormat(
				"yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
		String utcTime = sdf.format(new Date());
		return utcTime;
	}
	
	/**
	 * <h5>功能:</h5>组合创建一个模拟回调的xml文件
	 * @param SerialNum
	 * @param SystemNum
	 * @param chargeQueryMap
	 * @return 
	 *
	 * @author zhangpj	@date 2016年9月2日
	 */
	private static String creatBackRequestXml(String SerialNum,String SystemNum,Map<String, String> chargeQueryMap){
		StringBuffer bodyXml = new StringBuffer();
		bodyXml.append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
		bodyXml.append("<Request>");
		bodyXml.append("<Datetime>").append(chargeQueryMap.get("datetime")).append("</Datetime>");
		bodyXml.append("<Record>");
		bodyXml.append("<SerialNum>").append(SerialNum).append("</SerialNum>");
		bodyXml.append("<SystemNum>").append(SystemNum).append("</SystemNum>");
		bodyXml.append("<Mobile>").append(chargeQueryMap.get("mobile")).append("</Mobile>");
		bodyXml.append("<Status>").append(chargeQueryMap.get("status")).append("</Status>");
		bodyXml.append("<Description>").append(chargeQueryMap.get("description")).append("</Description>");
		bodyXml.append("<ChargeTime>").append(chargeQueryMap.get("chargeTime")).append("</ChargeTime>");
		bodyXml.append("</Record>");
		bodyXml.append("</Request>");
		
		return bodyXml.toString();
	}
	
	/**
	 * <h5>功能:</h5>获取充值查询结果,如果返回值是null则代表没有查询到订单
	 * 
	 * @param xml
	 * @return Map<String, String>
	 * 
	 * @author zhangpj @date 2016年8月24日
	 */
	private Map<String, String> getChargeQueryResult(String xml) {
		Document doc = null;
		Map<String, String> map = null;
		try {
			doc = DocumentHelper.parseText(xml); // 将字符串转为XML
			Element rootElt = doc.getRootElement(); // 获取根节点
			String datetime = rootElt.elementTextTrim("Datetime"); // 获取datetime叶子节点
			Element recordElement = rootElt.element("Records")
					.element("Record"); // 获取Record枝节点
			if (null != recordElement) {
				map = new HashMap<String, String>();
				String enterpriseId = recordElement
						.elementTextTrim("EnterpriseId"); // 获取SerialNum叶子节点
				String productId = recordElement.elementTextTrim("ProductId"); // 获取SystemNum叶子节点
				String mobile = recordElement.elementTextTrim("Mobile"); // 获取SystemNum叶子节点
				String status = recordElement.elementTextTrim("Status"); // 获取SystemNum叶子节点
				String description = recordElement
						.elementTextTrim("Description"); // 获取SystemNum叶子节点
				String chargeTime = recordElement.elementTextTrim("ChargeTime"); // 获取SystemNum叶子节点

				map.put("datetime", datetime);
				map.put("enterpriseId", enterpriseId);// 企业 ID
				map.put("productId", productId);// 产品编码
				map.put("mobile", mobile);// 充值电话号码
				map.put("status", status);// 充值结果状态,充值结果状态 1:订单已创建 2:已发送充值请求
											// 3:充值成功 4:充值失败
				map.put("description", description);// 充值结果描述信息
				map.put("chargeTime", chargeTime);// 充值时间
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return map;
	}
	
	/**
	 * <h5>功能:</h5>解析xml文件,获取Token信息
	 * 
	 * @author zhangpj @date 2016年8月23日
	 * @param xml
	 * @return
	 */
	private String getToken(String xml) {
		Document doc = null;
		String Token = "";
		try {
			doc = DocumentHelper.parseText(xml); // 将字符串转为XML
			Element rootElt = doc.getRootElement(); // 获取根节点
			Element authorizationElement = rootElt.element("Authorization"); // 获取Authorization枝节点
			Token = authorizationElement.elementTextTrim("Token"); // 获取Token叶子节点
		} catch (Exception e) {
			e.printStackTrace();
		}
		return Token;
	}
}
